package com.myblog.demo.controller;

import com.myblog.demo.common.*;
import com.myblog.demo.entity.ArticleInfo;
import com.myblog.demo.entity.UserInfo;
import com.myblog.demo.entity.vo.ArticleInfoVO;
import com.myblog.demo.service.ArticleService;
import com.myblog.demo.service.RedisServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RestController
@RequestMapping("/art")
public class ArticleController {
    @Autowired
    private ArticleService articleService;

    @Autowired
    private RedisServer redisServer;

    // 线程池
    private final ExecutorService service = Executors.newFixedThreadPool(ApplicationVariable.THREAD_NUMBER);

    /**
     * 添加文章
     *
     * @param articleInfo 传递对象而不是具体参数，方便后续扩展
     * @param request     用于获取 session，得到 uid
     * @return 返回统一类型
     */
    @RequestMapping("/add")
    public AjaxResult add(ArticleInfo articleInfo, HttpServletRequest request) {
        // 1. 非空判断
        if (articleInfo == null ||
                !StringUtils.hasLength(articleInfo.getTitle()) ||
                !StringUtils.hasLength(articleInfo.getContent())) {
            return AjaxResult.fail(-1, "参数错误！");
        }
        // 2. 得到 uid，组装数据
        UserInfo loginUser = UserSessionTools.getLoginUser(request);
        int uid = 0;
        if (loginUser != null) {
            uid = loginUser.getId();
        }
        articleInfo.setUid(uid);
        // 3. 持久化，根据结果返回 AjaxResult
        int result = articleService.add(articleInfo);
        return AjaxResult.success(result);
    }

    /**
     * 添加文章草稿
     *
     * @param articleInfo ArticleInfo
     * @param request     HttpServletRequest
     * @return 统一返回类型
     */
    @RequestMapping("/adddraft")
    public AjaxResult addDraft(ArticleInfo articleInfo, HttpServletRequest request) {
        // 1. 参数判断
        if (articleInfo == null ||
                !StringUtils.hasLength(articleInfo.getTitle()) ||
                !StringUtils.hasLength(articleInfo.getContent()) ||
                articleInfo.getState() != -1) {
            return AjaxResult.fail(-1, "参数错误！");
        }
        // 2. 得到 uid，组装数据
        UserInfo loginUser = UserSessionTools.getLoginUser(request);
        int uid = 0;
        if (loginUser != null) {
            uid = loginUser.getId();
        }
        articleInfo.setUid(uid);
        // 3. 持久化，根据结果返回 AjaxResult
        int result = articleService.addDraft(articleInfo);
        return AjaxResult.success(result);
    }

    /**
     * 获取文章详情信息，用于阅读文章，不需要鉴权
     *
     * @return 统一返回类型
     */
    @RequestMapping("/getdetail")
    public AjaxResult getDetailById(@RequestParam("id") Integer id) {
        // 1. 参数校验
        if (id == null || id <= 0) {
            return AjaxResult.fail(-1, "参数错误！");
        }
        // 2. 查询数据库，并返回结果
        ArticleInfoVO articleInfoVO = redisServer.getDetailById(id);
        return AjaxResult.success(articleInfoVO);
    }

    /**
     * 获取文章的详情信息，但是需要鉴权（判断文章的归属人是否为当前用户），用于修改文章
     *
     * @param id      文章id
     * @param request HttpServletRequest
     * @return 统一返回类型
     */
    @RequestMapping("/getdetailbyid")
    public AjaxResult getDetailByIdAndUid(Integer id, HttpServletRequest request) {
        // 非空判断
        if (id == null || id <= 0) {
            return AjaxResult.fail(-1, "参数错误！");
        }
        // 获取 session 中的用户uid
        UserInfo loginUser = UserSessionTools.getLoginUser(request);
        int uid = 0;
        if (loginUser != null) {
            uid = loginUser.getId();
        }
        // 通过 articleService 查询数据库，并将结果根据 AjaxResult 返回给前端
        ArticleInfo articleInfo = articleService.getDetailByIdAndUid(id, uid);
        return AjaxResult.success(articleInfo);
    }

    /**
     * 修改文章，需要鉴权
     *
     * @param articleInfo 要修改的文章信息
     * @param request     HttpServletRequest
     * @return 统一返回类型
     */
    @RequestMapping("/update")
    public AjaxResult update(ArticleInfo articleInfo, HttpServletRequest request) {
        // 1. 非空判断
        if (articleInfo == null ||
                !StringUtils.hasLength(articleInfo.getTitle()) ||
                !StringUtils.hasLength(articleInfo.getContent()) ||
                articleInfo.getId() <= 0) {
            return AjaxResult.fail(-1, "参数错误！");
        }

        // 2. 获取当前登录用户id, 并将其设置到 articleInfo
        UserInfo loginUser = UserSessionTools.getLoginUser(request);
        if (loginUser == null) {
            return AjaxResult.fail(-2, "当前用户未登录！");
        }

        int uid = loginUser.getId();
        articleInfo.setUid(uid);

        // 3. 通过 redisServer 对文章进行修改，并根据结果返回 AjaxResult
        int result = redisServer.updateArticle(articleInfo);
        return AjaxResult.success(result);
    }

    /**
     * 保存草稿功能
     *
     * @param articleInfo ArticleInfo
     * @param request     HttpServletRequest
     * @return AjaxResult
     */
    @RequestMapping("/savedraft")
    public AjaxResult saveDraft(ArticleInfo articleInfo, HttpServletRequest request) {
        // 参数合法性校验
        if (articleInfo == null ||
                !StringUtils.hasLength(articleInfo.getTitle()) ||
                !StringUtils.hasLength(articleInfo.getContent()) ||
                articleInfo.getId() <= 0 ||
                articleInfo.getState() != -1) {
            return AjaxResult.fail(-1, "参数错误！");
        }

        // 获取当前登录用户id
        UserInfo loginUser = UserSessionTools.getLoginUser(request);
        int uid = loginUser != null ? loginUser.getId() : 0;
        articleInfo.setUid(uid);

        int result = articleService.saveDraft(articleInfo);
        return AjaxResult.success(result);
    }

    /**
     * 增加阅读量，每次执行该请求就增加一次
     *
     * @param id 文章id
     * @return 统一返回类型
     */
    @RequestMapping("/addrcount")
    public AjaxResult addRCount(@RequestParam("id") Integer id) {
        if (id == null || id <= 0) {
            return AjaxResult.fail(-1, "参数错误！");
        }

        int result = articleService.addRCount(id);
        return AjaxResult.success(result);
    }

    /**
     * 获取当前用户的博客列表，需要鉴权
     *
     * @param request HttpServletRequest
     * @return 统一返回类型
     */
    @RequestMapping("/mylist")
    public AjaxResult getMyList(HttpServletRequest request) {
        // 获取当前用户id
        UserInfo loginUser = UserSessionTools.getLoginUser(request);

        // 可以不用判断，过了拦截器保证了此时用户一定登录了
        if (loginUser == null) {
            return AjaxResult.fail(-2, "当前用户未登录！");
        }

        int uid = loginUser.getId();
        List<ArticleInfo> list = articleService.getListByUid(uid);
        // 截取文章内容形成文章摘要，并移除 Markdown 关键字
        // 多线程并发循环
        list.stream().parallel().forEach(item -> {
            String subContent = StringTools.subLength(item.getContent(), 300);
            // 将 subContent 中的 markdown 关键字去除
            String plainText = MarkdownUtils.removeMarkdown(subContent);
            item.setContent(plainText);
        });

        /*for (ArticleInfo item : list) {
            String subContent = StringTools.subLength(item.getContent(), 300);
            // 将 subContent 中的 markdown 关键字去除
            String plainText = MarkdownUtils.removeMarkdown(subContent);
            item.setContent(plainText);
        }*/
        return AjaxResult.success(list);
    }


    /**
     * 获取指定用户的博客列表
     *
     * @param uid 用户id
     * @return AjaxResult
     */
    @RequestMapping("/getlistbyuid")
    public AjaxResult getListByUId(Integer uid) {
        if (uid == null || uid <= 0) {
            return AjaxResult.fail(-1, "参数错误！");
        }

        List<ArticleInfo> list = articleService.getListByUid(uid);
        // 截取文章内容形成文章摘要，并移除 Markdown 关键字
        // 多线程并发循环
        list.stream().parallel().forEach(item -> {
            String subContent = StringTools.subLength(item.getContent(), 300);
            // 将 subContent 中的 markdown 关键字去除
            String plainText = MarkdownUtils.removeMarkdown(subContent);
            item.setContent(plainText);
        });
        return AjaxResult.success(list);
    }

    /**
     * 获取当前用户的草稿列表
     *
     * @param request HttpServletRequest
     * @return 统一返回类型
     */
    @RequestMapping("/mydraftlist")
    public AjaxResult getDraftList(HttpServletRequest request) {
        // 获取当前用户id
        UserInfo loginUser = UserSessionTools.getLoginUser(request);
        if (loginUser == null) {
            return AjaxResult.fail(-2, "当前用户未登录！");
        }

        Integer uid = loginUser.getId();

        // 获取草稿列表
        List<ArticleInfo> list = articleService.getDraftList(uid);
        list.stream().parallel().forEach(item -> {
            String subContent = StringTools.subLength(item.getContent(), 150);
            // 将 subContent 中的 markdown 关键字去除
            String plainText = MarkdownUtils.removeMarkdown(subContent);
            item.setContent(plainText);
        });

        return AjaxResult.success(list);
    }

    /**
     * 根据接收到的文章id删除指定文章，但需要鉴定文章的归属作者是否合法
     *
     * @param id      要删除的文章id
     * @param request HttpServletRequest
     * @return 统一返回类型
     */
    @RequestMapping("/del")
    public AjaxResult delByIdAndUid(@RequestParam("id") Integer id, HttpServletRequest request) {
        // 参数合法性判断
        if (id == null || id <= 0) {
            return AjaxResult.fail(-1, "参数错误！");
        }

        // 判断当前用户是否登录
        UserInfo loginUser = UserSessionTools.getLoginUser(request);
        if (loginUser == null) {
            return AjaxResult.fail(-2, "当前用户未登录！");
        }

        // 通过 RedisService 从数据库中删除文章，并根据结果返回
        int uid = loginUser.getId();
        int result = redisServer.deleteArticleByAIdAndUID(id, uid);
        return AjaxResult.success(result);
    }


    @RequestMapping("/getlistbypage")
    public AjaxResult getListByPage(Integer pageSize, Integer pageIndex) {
        // 默认值处理
        if (pageSize == null || pageSize <= 0) {
            // 没有传递参数的时候指定一个默认值
            pageSize = 2;
        }
        if (pageIndex == null || pageIndex <= 0) {
            pageIndex = 1;
        }

        // 分页公式：计算偏移量
        int offset = (pageIndex - 1) * pageSize;

        // 从数据库中获取分页列表
        List<ArticleInfo> list = articleService.getListByPage(pageSize, offset);
        // 截取文章内容形成文章摘要，并移除 Markdown 关键字
        // 多线程并发循环
        list.stream().parallel().forEach(item -> {
            String subContent = StringTools.subLength(item.getContent(), 300);
            // 将 subContent 中的 markdown 关键字去除
            String plainText = MarkdownUtils.removeMarkdown(subContent);
            item.setContent(plainText);
        });

/*        for (ArticleInfo item : list) {
            String subContent = StringTools.subLength(item.getContent(), 300);
            // 将 subContent 中的 markdown 关键字去除
            String plainText = MarkdownUtils.removeMarkdown(subContent);
            item.setContent(plainText);
        }*/
        return AjaxResult.success(list);
    }

    /**
     * 获取文章总数
     *
     * @return 统一返回类型
     */
    @RequestMapping("/getcount")
    public AjaxResult getCount() {
        int result = articleService.getCount();
        return AjaxResult.success(result);
    }

    /**
     * 查询用户名为 username 的文章总数
     *
     * @param username 用户名
     * @return 统一返回类型
     */
    @RequestMapping("/getcountbyusername")
    public AjaxResult getCountByUid(String username) {
        if (!StringUtils.hasLength(username)) {
            return AjaxResult.fail(-1, "参数错误！");
        }
        int result = articleService.getCountByUsername(username);
        return AjaxResult.success(result);
    }

    /**
     * 定时发布功能
     *
     * @param request HttpServletRequest
     * @return AjaxResult
     */
    @RequestMapping("/addtime")
    public AjaxResult timeSub(ArticleInfo articleInfo, String postTime, HttpServletRequest request) {
        // 参数校验
        if (articleInfo == null ||
                !StringUtils.hasLength(articleInfo.getTitle()) ||
                !StringUtils.hasLength(articleInfo.getContent()) ||
                !StringUtils.hasLength(postTime)) {
            return AjaxResult.fail(-1, "参数错误!");
        }

        UserInfo loginUser = UserSessionTools.getLoginUser(request);
        if (loginUser == null) {
            return AjaxResult.fail(-2, "当前用户未登录！");
        }

        // 设置参数
        int uid = loginUser.getId();
        articleInfo.setUid(uid);

        // 将postTime字符串转换为LocalDateTime
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime parsedPostTime = LocalDateTime.parse(postTime, formatter);
        articleInfo.setCreatetime(parsedPostTime);

        System.out.println(articleInfo);


        // 设置定时发布，启动一个线程，每隔10秒询问是否到达指定时间

        // 定义时间格式
        // SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        /* Thread queryPostTime = new Thread(() -> {
            synchronized (lock) {
                while (true) {
                    if (CheckTimeTools.checkTimeout(articleInfo.getCreatetime())) {
                        // 到达了预定时间，添加文章
                        articleService.add(articleInfo);
                        break;

                    } else {
                        try {
                            System.out.println("休眠10秒");
                            lock.wait(10000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });

        queryPostTime.start();*/

        service.submit(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if (CheckTimeTools.checkTimeout(articleInfo.getCreatetime())) {
                        // 到达了预定时间，添加文章
                        articleService.add(articleInfo);
                        break;
                    } else {
                        try {
                            System.out.println("休眠10秒");
                            Thread.sleep(10000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });

        return AjaxResult.success(1);
    }

    /**
     * 根据文章id获取作者信息
     *
     * @param id 文章id
     * @return AjaxResult
     */
    @RequestMapping("/getuserinfobyartid")
    public AjaxResult getUserInfoByArtId(Integer id) {
        if (id == null || id <= 0) {
            return AjaxResult.fail(-1, "参数错误！");
        }

        UserInfo userInfo = articleService.getUserInfoByArtId(id);
        return AjaxResult.success(userInfo);
    }

    /**
     * 根据关键字，模糊搜索文章列表
     *
     * @param key 关键字
     * @return AjaxResult
     */
    @RequestMapping("/search")
    public AjaxResult getListByLikeTitle(String key) {
        // 参数校验
        if (!StringUtils.hasLength(key)) {
            return AjaxResult.fail(-1, "参数错误！");
        }

        List<ArticleInfo> list = articleService.getListByLikeTitle(key);
        // 获取文章内容，形成摘要，并去除markdown语法关键字
        list.stream().parallel().forEach(item -> {
            String subContent = StringTools.subLength(item.getContent());
            // 去除markdown语法关键字
            String plainText = MarkdownUtils.removeMarkdown(subContent);
            item.setContent(plainText);
        });
        return AjaxResult.success(list);
    }
}
